//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package webhook_serv_atomgit

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"time"

	"atomgit.com/openlinksaas/api-server/dao/event_dao"
	"atomgit.com/openlinksaas/proto-gen-go.git/events_api"
	atomgit_hook "atomgit.com/openlinksaas/webhook.git/atomgit"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"google.golang.org/protobuf/types/known/anypb"
)

var sourceType zapcore.Field

func init() {
	sourceType = zap.String("sourceType", "atomgit")
}

func Process(projectId, eventSourceId string, header http.Header, payload []byte, secret string, logger *zap.Logger) (*event_dao.EventStageDbItem, *anypb.Any, error) {
	timeStamp := time.Now().UnixNano() / 1e6
	eventStr := strings.ToLower(header.Get("X-AtomGit-Event"))
	if eventStr == "push" || eventStr == "tag_push" {
		return processPush(projectId, eventSourceId, payload, timeStamp, logger)
	} else if strings.Contains(eventStr, "issues") {
		return processIssue(projectId, eventSourceId, payload, timeStamp, logger)
	} else {
		logger.Error("wrong webhook event type", zap.String("projectId", projectId), zap.String("eventSourceId", eventSourceId), sourceType)
		return nil, nil, fmt.Errorf("unkwown event data")
	}
}

func processPush(projectId, eventSourceId string, payload []byte, timeStamp int64, logger *zap.Logger) (*event_dao.EventStageDbItem, *anypb.Any, error) {
	logger.Info("recive push event", zap.String("projectId", projectId), zap.String("eventSourceId", eventSourceId), sourceType)
	pushHook := &atomgit_hook.PushHook{}
	err := json.Unmarshal(payload, pushHook)
	if err != nil {
		logger.Error("unmarshal failed", zap.String("projectId", projectId), zap.String("eventSourceId", eventSourceId), sourceType, zap.String("payload", string(payload)))
		return nil, nil, err
	}
	issueEvent := pushHook.ToProtoBuf()
	eventAny, err := anypb.New(issueEvent)
	if err != nil {
		logger.Error("convert event failed", zap.String("projectId", projectId), zap.String("eventSourceId", eventSourceId), sourceType)
		return nil, nil, err
	}
	sourceUserName := pushHook.Sender.Login
	sourceDisplayName := pushHook.Sender.Login
	stageItem := &event_dao.EventStageDbItem{
		ProjectId:         projectId,
		EventSourceId:     eventSourceId,
		SourceUserName:    sourceUserName,
		SourceDisplayName: sourceDisplayName,
		EventType:         uint32(events_api.EVENT_TYPE_EVENT_TYPE_ATOMGIT),
		EventTime:         timeStamp,
	}
	return stageItem, eventAny, nil
}

func processIssue(projectId, eventSourceId string, payload []byte, timeStamp int64, logger *zap.Logger) (*event_dao.EventStageDbItem, *anypb.Any, error) {
	logger.Info("recive issue event", zap.String("projectId", projectId), zap.String("eventSourceId", eventSourceId), sourceType)
	issueHook := &atomgit_hook.IssueHook{}
	err := json.Unmarshal(payload, issueHook)
	if err != nil {
		logger.Error("unmarshal failed", zap.String("projectId", projectId), zap.String("eventSourceId", eventSourceId), sourceType, zap.String("payload", string(payload)))
		return nil, nil, err
	}
	issueEvent := issueHook.ToProtoBuf()
	eventAny, err := anypb.New(issueEvent)
	if err != nil {
		logger.Error("convert event failed", zap.String("projectId", projectId), zap.String("eventSourceId", eventSourceId), sourceType)
		return nil, nil, err
	}
	sourceUserName := issueHook.Sender.Login
	sourceDisplayName := issueHook.Sender.Login
	stageItem := &event_dao.EventStageDbItem{
		ProjectId:         projectId,
		EventSourceId:     eventSourceId,
		SourceUserName:    sourceUserName,
		SourceDisplayName: sourceDisplayName,
		EventType:         uint32(events_api.EVENT_TYPE_EVENT_TYPE_ATOMGIT),
		EventTime:         timeStamp,
	}
	return stageItem, eventAny, nil
}
